home *** CD-ROM | disk | FTP | other *** search
- .lh 6
- .cw 7
- .mt 4
- .mb 11
- .pl 88
- .op
-
- APPLICATIONS: Using ASMGEN to disassemble MORE.COM
- .he ASMGEN disassembly of MORE.COM Page #
-
- The primary justification for writing programs in assembly
- language is execution speed. Few would argue in favor of such
- direct machine contact if there were easier ways to achieve the
- performance improvements that are possible in comparison with
- high-level programs like BASIC and Pascal.
-
- The best way to achieve some level of literacy in assembly
- language programming is to examine the programs written by
- others. You can incorporate segments of their code in your
- programs--or modify their programs to serve your own application.
-
- Programs available in the public domain are ideal for this
- purpose, since the sheer variety of programs raises the
- likelihood that you will be able to find something close to what
- you need. Unfortunately, they do not all come with the source
- code.
-
- For modifying programs for which you do not have the source
- code, there is a disassembler available (again, in the public
- domain) which you can use to reconstruct the basic program
- structure. Named ASMGEN, it was written by Jack Gersbach and
- J. Damke. (It turns out he is also the co-author of one of the
- utilities packages now being marketed by IBM in its Personally
- Developed Software series.) It available on Windmill, Thousand
- Oaks, Simi, RIMS and most other public domain bulletin boards.
- Look for version 2.01 or later.
-
- We've chosen for an example the DOS filter MORE.COM. This
- modest little program at 384 bytes is the smallest of the three filters
- supplied with DOS. The other two, FIND.COM and SORT.COM, are
- considerably more complex. MORE.COM provides in its small space
- assembly language examples of the following operations (in rough
- order of appearance in the program):
-
- . Checking for DOS version number (2.00 or higher)
- . Activating the required input and standard error devices
- . Reading standard input into a buffer
- . Using DOS file handles instead of File Control Blocks
- . Using a System BIOS call for checking the width of the
- current screen
- . Managing a "shadow screen" to keep track of the cursor
- . Checking input for end of file, enter, line feed,
- backspace, tab and bell (beep) characters
- . Correctly adjusting screen display for 8-space tab
- . Wrapping the screen display if the line width exceeds
- the screen width, whether it is 40 or 80 columns wide
- . Pausing the display at each full screen, and waiting for a
- keypress to proceed
-
-
- To do this sort of disassembly operation properly, you need
- a number of tools. A complete list comprises the following items:
-
- . Disassembler: ASMGEN, V2.01 or later by Gersbach/Damke
- (Public Domain)
- . File compare: CMP10, V1.10 or later by Gersbach
- (Public Domain)
- . Concurrent text editor and utility: The Notepad and the
- Calculator features of SideKick, V1.10B
- from Borland International
- . Main text editor: WordStar 3.3 in non-document mode
- from MicroPro International
- . Macro Assembler V1.00, from IBM/Microsoft
- .cp 5
- . Manuals:
- Disk Operating System Reference Manual
- Disk Operating System Technical Reference Manual
- Technical Reference Personal Computer XT and
- Portable Personal Computer
- A reference manual on the Intel 8086/8088 instruction set
-
- There is no point in attempting a disassembly of any size
- without the DOS Technical Reference Manual. IBM and Microsoft
- have moved all the required DOS function call information into a
- separate manual starting with version 2.10. It is possible to
- get by with the integrated DOS version 2.00 manual for the
- function calls, but only as a last resort.
-
- The hardware manual is another absolute requirement because
- it is only in the System BIOS program listing that you will find
- what the BIOS function calls mean. Even a program as nominally
- trivial as MORE.COM uses a BIOS call to determine the width of
- the current display screen. You will not be able to decode the
- system interrupts without this manual.
-
- The Macro Assembler is also required. Unlike CP/M, DOS
- comes with no assembler. The only facility it has to assemble
- programs is the "A" command in DEBUG, which will assemble into
- memory the instructions you enter via the keyboard. This is on
- the same approximate level as the Apple II monitor ROM assembler.
-
- Since you must have the macro assembler, you might as well
- use its macro facility. As you will see in the reconstructed
- program listing that follows, all the BIOS and DOS function calls
- have been recoded as macros. This allows you to remove yourself
- from the requirement of remembering the purpose of each of the
- hexadecimal functions, and shows more clearly the underlying flow
- of the program in a language that you can define yourself that
- makes most sense to you. This is how you can build up your DOS
- function library.
-
- Unfortunately, ASMGEN does not take its interpretation this
- far; it is up to you to replace the INT 21 forms with the
- appropriate macro call. Equally unfortunately, the DOS Technical
- Reference Manual is mainly organized along the lines of the
- hexadecimal function number, so you may find yourself referring
- back to the macro definition to find the hex value of the call so
- that you can locate its reference in the DOS manual. Sigh...
-
- It would be difficult to imagine undertaking this sort of
- exercise without SideKick. SideKick has a "notepad", which can
- function as a concurrent text editor. SideKick has all the
- features and command syntax of WordStar with the exception of
- word wrap (not needed in the context of programming). It remains
- resident so that by invoking it with the <shift><shift> keys
- (holding down both <shift> keys simultaneously) you can edit the
- .SEQ file required by ASMGEN to interpret the .COM file without
- the delay of reloading and then unloading the main text editor.
- A superior utility.
-
- We use WordStar for word processing and text editing. There
- are other word processors available. For this type of work,
- where you are doing programming and debugging, you need windows.
- We use SideKick for that purpose. You might also try XyWrite II
- Plus (two windows), or FinalWord (multiple windows). Pmate also
- has multiple edit buffers, but is thoroughly inscrutable.
- Microsoft Word supports up to eight windows, but the entry/exit
- overhead is too much and the internal format must be translated
- to ASCII before it can be used. XyWrite takes a some setup time
- as well, but it provides a facility whereby you can drop down to
- DOS and back again very quickly.
-
- Finally, the file compare program CMP10, also by Jack
- Gersbach. This too is a public domain program. The absolute
- first objective of a disassembly is the reconstruction of the
- original file--byte for byte. The program listing that follows,
- with all its macro definitions, will assemble, link, EXE2BIN and
- REN into a .COM file that is absolutely identical to the source
- .COM file. It is only after you have achieved this objective
- that you should feel comfortable about modifying the
- reconstructed .ASM file for your own purposes.
-
- DOS provides a file compare program (COMP.COM), but
- unfortunately if the files are of different lengths the utility
- stops. This is of little use, since in most cases almost all
- efforts at reassembly except for the very last will result in
- .COM files of different lengths. CMP10 will compare files of
- different lengths and show the differences as well--in hex and
- ASCII format similar to a DEBUG display listing. Indispensable.
-
- The reassembled and reconstituted source file for MORE.COM
- follows. The source code shown here will generate a .COM file
- that is absolutely identical, byte for byte, with the original
- DOS 2.00 version from which it was constructed. It has been
- checked against DOS Version 3.00. With the exception of a
- slightly shorter buffer tail at the end of the program, DOS 3.00
- is identical byte-for-byte to the DOS 2.00 program.
-
-
- R. Zider
- San Francisco, CA
- 11.18.84
- Copyright 1984. All right reserved.
- Released to the public domain for personal use only.
- .pa
- REASSEMBLY OF MORE.COM Exhibit 1
-
- Listing of MOR.ASM
- ------------------
-
-
-
- TITLE MOR 3-8-83 [11-17-84]
- ;
- ; Reassembly of IBM PC DOS 2.00 MORE.COM filter
- ;
- ; R. Zider Zider Brothers, San Francisco
- ;
- ;
- .RADIX 16
- BEL EQU 07H
- BKSP EQU 08H
- TAB EQU 09H
- LF EQU 0AH
- CR EQU 0DH
- EOF EQU 1AH
- ;
- ; MACRO DEFINITIONS
- ;
- ;SYSTEM BIOS MACROS
- ;
- VIDEO_BIOSCALL MACRO
- ;;Invoke System BIOS video I/O function call
- ;;On entry:
- ;;(AH) = Function number
- ;;See page 5-68ff Technical Reference Personal Computer XT and
- ;; Portable Personal Computer
- INT 10H
- ENDM
- ;
- GET_CURRENT_VIDEO_STATE MACRO
- ;;Get screen width using a video BIOS call
- ;;On entry:
- ;;If (AH) = 15 (0FH), then function returns current video state
- ;;On exit:
- ;;"(AL) = Mode currently set (see AH=0 for explanation)"
- ;;"(AH) = Number of character columns on screen"
- ;;"(BH) = Current active display page"
- ;; Quoted from TRM page 5-69
- MOV AH,0FH
- VIDEO_BIOSCALL
- ENDM
- ;
- ;
- ;DOS MACROS
- ;
- DOS_EXIT MACRO
- INT 20H
- ENDM
- ;
- DOSCALL MACRO
- ;;Standard DOS function call
- ;;On entry:
- ;;(AH) = Function call number
- INT 21H
- ENDM
-
- CLEAR_KB_INPUT MACRO
- ;;Clear keyboard buffer, read char from std input device (keyboard)
- ;;Character returned in (AL)
- MOV AH,0CH ;;Clear KB buffer (plus function in AL)
- MOV AL,1H ;;Read char from KB function
- DOSCALL
- ENDM
- ;
- .cp 5
- DOS_DISPLAY_OUT MACRO
- ;;(DL) has the character to be displayed
- MOV AH,2H
- DOSCALL
- ENDM
- ;
- DOS_PRINT_STRING MACRO STRING_LABEL
- ;Output a "$"-terminated string
- MOV DX,OFFSET STRING_LABEL
- MOV AH,9H
- DOSCALL
- ENDM
- ;
- GET_DOS_VERSION MACRO
- ;;Version number returned in two pieces:
- ;;(AL) = Major version number (as "02" or "03")
- ;;(AH) = Minor version number (as "00" or "01")
- MOV AH,30H
- DOSCALL
- ENDM
- ;
- CLOSE_FILE_HANDLE MACRO
- ;;On entry:
- ;;(BX) = File handle returned by "open" or "create"
- ;;On exit:
- ;;(AX) = Error codes (NONE if carry not set)
- MOV AH,3EH
- DOSCALL
- ENDM
- ;
- READ_FROM_FILE MACRO HANDLE, BYTES, BUFFER
- ;;Transfer bytes from a file into a buffer
- ;;On entry:
- ;;(BX) = File handle of source file
- ;;(CX) = Number of bytes to be read (max--may be less than this)
- ;;(DX) = Location of destination buffer
- ;;On exit:
- ;;(AX) = Number of bytes actually read; or else error code if carry set
- MOV DX, OFFSET BUFFER
- MOV CX, BYTES
- MOV BX, HANDLE
- MOV AH,3FH
- DOSCALL
- ENDM
- ;
- DUP_FILE_HANDLE MACRO ;;HANDLE argument not yet implemented
- ;;This function duplicates a file handle
- ;;On entry:
- ;;(BX) = File handle to be duplicated
- ;;On exit:
- ;;(AX) = New file handle, referring to same file at same position
- ;; (or else error codes if carry set)
- ;; MOV BX, HANDLE ;;Need conditional assembly if arg missing
- MOV AH,45H
- DOSCALL
- ENDM
- ;
- ; PROGRAM STARTS HERE
- ;
- ;
- ;INITIAL VALUES : CS:IP 0000:0100
- ; SS:SP 0000:FFFF
- S0000 SEGMENT
- ASSUME DS:S0000, SS:S0000 ,CS:S0000 ,ES:S0000
- ORG $+0100H
- START: GET_DOS_VERSION ;Check DOS version first
- XCHG AH,AL ;Put major version in AH, minor in AL
- CMP AX,200 ;Must be 2.00 or higher
- JNB OK_VER_200
- DOS_PRINT_STRING WRONG_DOS ;Nope..
- DOS_EXIT ;..bye
- .cp 5
- OK_VER_200:
- MOV BYTE PTR SCREEN_HEIGHT,19 ;Screen height 25 lines
- GET_CURRENT_VIDEO_STATE ;Not sure of width, though--get it
- MOV SCREEN_WIDTH,AH ;OK, save current width
- DOS_PRINT_STRING CR_LF ;Flush screen with a CR-LF
- XOR BX,BX ;Zero BX to get a duplicate..
- DUP_FILE_HANDLE ;..file handle of std input (handle 0)
- MOV BP,AX ;New file handle to BP
- CLOSE_FILE_HANDLE ;Close handle 0 (std input)--use dup
- MOV BX,2 ;Default handle 2 is std error output..
- DUP_FILE_HANDLE ;..device--activate it
-
- READ_STD_INPUT_INTO_BUFFER:
- CLD ;Clear direction
- ; MOV DX,OFFSET BUFFER ;Destination buffer
- ; MOV CX,1000 ;Max of 1000H bytes (4KB)
- ; MOV BX,BP ;This has new std input file handle
- READ_FROM_FILE BP 1000 BUFFER ;OK, read on..
- ;..and ignore any error return
- OR AX,AX ;Check for non-zero bytes read
- JNZ OK_READ ;"OK" if non-zero
- EXIT: DOS_EXIT ;Empty std input file--bye
-
- OK_READ:
- MOV CX,AX ;Number of bytes read to CX
- MOV SI,DX ;Buffer location to SI (now source)
- LOAD_NEXT_BYTE:
- LODSB ;Start processing bytes..
- CMP AL,EOF ;..looking for an end-of-file (1AH)..
- JZ EXIT ;..and exit if found
- CMP AL,CR ;Check if it is a carriage return..
- JNZ CK_LINEFEED ;..and if not, continue on with check
- MOV BYTE PTR COLUMN_COUNT,1 ;CR, so reset to screen column 1 and..
- JMP SHORT DISPLAY_OUT ;..output the CR to the screen
-
- CK_LINEFEED:
- CMP AL,LF ;Check if it is a line feed (OAH)..
- JNZ CK_BKSPACE ;..and if not, go to next char check
- INC BYTE PTR LINE_COUNT ;LF, so bump the line count and..
- JMP SHORT DISPLAY_OUT ;..output the LF to the screen
-
- CK_BKSPACE:
- CMP AL,BKSP ;Check for backspace char (08H)..
- JNZ CK_TAB ;..and if not, continue on to next
- CMP BYTE PTR COLUMN_COUNT,1 ;Is backspace, check if at column 1..
- JZ DISPLAY_OUT ;..and if so, just output the char
- DEC BYTE PTR COLUMN_COUNT ;Not at column 1, so dec the column..
- JMP SHORT DISPLAY_OUT ;..and output the backspace
-
- CK_TAB: CMP AL,TAB ;Check for tab char (09H)..
- JNZ CK_BEL ;..and if not, press on
- MOV AH,COLUMN_COUNT ;Is tab, so get the current column..
- ADD AH,7 ;..add 7 to it..
- AND AH,0F8 ;..and mask for MOD 8..
- INC AH ;..adding one..
- MOV COLUMN_COUNT,AH ;..and make this the new column..
- JMP SHORT DISPLAY_OUT ;..and output it to the display
-
- CK_BEL: CMP AL,BEL ;Check for BEL (beep) char (07)
- JZ DISPLAY_OUT ;Is a BEL, so let console handle it
- INC BYTE PTR COLUMN_COUNT ;None of these, so bump the column..
- MOV AH,COLUMN_COUNT ;..and check to see if we're at the
- CMP AH,SCREEN_WIDTH ;..edge of the screen..
- JBE DISPLAY_OUT ;..and if not, output the character
- INC BYTE PTR LINE_COUNT ;At screen edge, so do a line wrap..
- MOV BYTE PTR COLUMN_COUNT,1 ;..and bump the line and reset to col 1
-
- DISPLAY_OUT:
- MOV DL,AL ;Output the character..
- DOS_DISPLAY_OUT ;..to the display via DOS call
- MOV AH,LINE_COUNT ;Check the line count..
- CMP AH,SCREEN_HEIGHT ;..against the screen height..
- JB NEXT_BYTE ;..and continue if no overflow
- DOS_PRINT_STRING MORE_LINE ;"--More--" message..
- CLEAR_KB_INPUT ;..and pause for keyboard input
- DOS_PRINT_STRING CR_LF ;OK, continue and clear More line..
- MOV BYTE PTR COLUMN_COUNT,1 ;..reset screen pointers to Home..
- MOV BYTE PTR LINE_COUNT,1 ;..at top left position (1,1)
- DEC SI ;Back up one byte in buffer so that..
- INC CX ;..the byte can be re-sent
-
- NEXT_BYTE:
- DEC CX ;One less byte to do, and..
- JZ RD_NEXT_4K ;..if now zero, read another 4KB
- JMP LOAD_NEXT_BYTE ;A computer's work is never done
-
- RD_NEXT_4K:
- JMP READ_STD_INPUT_INTO_BUFFER ;Heigh Ho, Heigh Ho...
-
- SCREEN_HEIGHT EQU $
- DB 18 ;24 lines, but gets overwritten
- SCREEN_WIDTH EQU $
- DB 50 ;Here, 80 columns wide (overwtritten)
- LINE_COUNT EQU $
- DB 1 ;Starts at 1
- COLUMN_COUNT EQU $
- DB 1,5 DUP(0) ;Starts at 1
- MORE_LINE EQU $
- DB CR,'-- More --$' ;Displayed on 25th line
- WRONG_DOS EQU $
- DB 'MORE: Incorrect DOS version'
- CR_LF EQU $
- DB CR,LF,'$'
- BUFFER EQU $
- DB 66 DUP(0) ;Read buffer only 66H bytes here
- S0000 ENDS
- ;
- END START
-
- .pa
- MORE.ASM Exhibit 2
-
- Assembly and link to .COM file
- ------------------------------
-
- This is what you will have to do to get a .COM file that you
- can compare with the original MORE.COM program in DOS 2.00. The
- following listing has been captured from the screen display with
- FSPOOL.COM.
-
- B>dir
-
- Volume in drive B is PCDISASM
- Directory of B:\mor
-
- . <DIR> 11-04-84 2:17p
- .. <DIR> 11-04-84 2:17p
- M OBJ 536 11-17-84 7:24p
- MOR ASM 2468 11-17-84 9:10a
- M LST 15785 11-17-84 7:24p
- M COM 384 11-17-84 7:21p
- MOR OBJ 501 11-17-84 11:53a
- MOR SEQ 617 11-17-84 9:07a
- M EXE 1152 11-17-84 7:24p
- MORE300 COM 320 8-14-84 8:00a
- MORE COM 384 3-08-83 12:00p
- M BIN 384 11-17-84 7:24p
- M ASM 7168 11-17-84 4:39p
- MOR COM 384 11-17-84 11:54a
- N LST 15785 11-17-84 7:14p
- NOTES 3525 11-17-84 7:04p
- T PRN 512 11-17-84 7:44p
- 17 File(s) 181248 bytes free
-
- B>masm m
- Bad command or file name
-
- B>a:ini
-
- B>path=a:\
- B>masm m
- The IBM Personal Computer MACRO Assembler
- Version 1.00 (C)Copyright IBM Corp 1981
-
- Object filename [M.OBJ]:
- Source listing [NUL.LST]: m.lst
- Cross reference [NUL.CRF]:
-
- Warning Severe
- Errors Errors
- 0 0
-
- B>link m
-
- IBM Personal Computer Linker
- Version 2.00 (C)Copyright IBM Corp 1981, 1982, 1983
-
- Run File [M.EXE]:
- List File [NUL.MAP]:
- Libraries [.LIB]:
- Warning: No STACK segment
-
- There was 1 error detected.
-
- B>exe2bin m
-
- B>cmp10 m.bin more.com
- Files are identical
-
- .cp 15
- B>dir m.*
-
- Volume in drive B is PCDISASM
- Directory of B:\mor
-
- M OBJ 536 11-17-84 7:46p
- M LST 15785 11-17-84 7:46p
- M COM 384 11-17-84 7:21p
- M EXE 1152 11-17-84 7:47p
- M BIN 384 11-17-84 7:47p
- M ASM 7168 11-17-84 4:39p
- 6 File(s) 180224 bytes free
-
- B>fspool